package Project;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

import javax.swing.JFrame;

import java.awt.Dimension;
import java.awt.Frame;
import java.awt.MouseInfo;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import ADTs.FileADT;
import ADTs.LevelStateADT;
import ADTs.PointADT;

/**
 * This is the Main class of the game.
 * 
 * @author	Brian Wetherbee
 * 			Ryan McNamara
 * 			Zeng Yang
 * 
 * 
 * PS: Data structures always have the format of [name]ADT.java
 */
public class Main extends JFrame implements ComponentListener, WindowListener {
	
	//@ public invariant Constants.CONSTANTS_SET_UP == true;
	//@ public invariant Main.INIT_CALLED == true;
	//@ public invariant playerInLevel == true ==> Main.CurrentUI instanceof Level
	private /*@ spec_public @*/ static boolean INIT_CALLED = false;
	
	public static /*@ spec_public @*/ boolean playerInLevel = false;
	private static /*@ spec_public @*/ UI CurrentUI;
	private static ArrayList<UI> UIList = null;
	private static Main game;
	
	
	
	/*@ requires Main.INIT_CALLED == false;
	  @  ensures Main.INIT_CALLED == true;
	 */
	private static void Init(){
		
	}
	
	//ensures false is correct since control should NEVER reach past this method
	/*@ requires true;
	  @ ensures false;
	 */
	public static void Quit(){
		
	}
	
	
	/**
     * Creates new form Main
     */
    public Main() {
    	this.setUndecorated(true);
    	Main.game = this;
    	
    	this.addWindowListener(this);//
        

        initComponents();
        setBackground(java.awt.Color.BLACK);
        
        CurrentUI = new TitleScreen();
        CurrentUI.setFocusable(true);
        CurrentUI.requestFocusInWindow();
        getContentPane().add(CurrentUI);
        
    }

    
    
    private void initComponents() {

		this.setUndecorated(false);
    	//Init specific stuff
    	INIT_CALLED = true;
    	Constants.setUpConstants();
    	
    	this.addComponentListener(this);
    	
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setBackground(new java.awt.Color(0, 0, 0));

        pack();
        this.setState(Frame.NORMAL);
        Toolkit toolkit = Toolkit.getDefaultToolkit();
		Dimension dimension = toolkit.getScreenSize();

		this.setSize(dimension);
    }                  
                        

    public static void setCurrentUI(int uiNum)
    {
    	
    	UI toSet = null;
    	if(uiNum == Constants.TitleScreenNum) {
    		toSet = new TitleScreen();
    	}
    	else if(uiNum == Constants.StoryNum) {
    		toSet = new Story();
    	}
    	else if(uiNum == Constants.GalaxyMapNum){
    		toSet = new GalaxyMap();
    	}
    	else if(uiNum == Constants.TitleScreenLoadGame){
    		toSet = new TitleScreenLoadGame();
    	}
    	setCurrentUI(toSet);
    	
    	
    	
    }
    public static void setCurrentUI(UI toSet){
    	//take away the old one
    	CurrentUI.setVisible(false);
    	CurrentUI.setFocusable(false);
    	game.getContentPane().remove(CurrentUI);
    	
    	//add the new one
    	CurrentUI = toSet;
    	game.getContentPane().add(CurrentUI);
    	
    	CurrentUI.setVisible(true);
		CurrentUI.setFocusable(true);
		CurrentUI.requestFocusInWindow();
		CurrentUI.repaint();
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                game = new Main();
                game.setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify                     
    // End of variables declaration                   
 


	public static UI getCurrentUI() {
		return CurrentUI;
	}

	public static PointADT getMouseLocation(){
		PointADT result = new PointADT(MouseInfo.getPointerInfo().getLocation());
		
		result.xAdd(-game.getInsets().left-game.getLocation().x);
		result.yAdd(-game.getInsets().top-game.getLocation().y);
		result.actualToInternal();
		
		return result;
	}
	
	
	public static double internalToActualX(double x){
		double scale = Main.getActualComponentSize().getX() / (double)Constants.width ;
		return (x * scale);
	}
	
	public static double internalToActualY(double y){
		double scale = Main.getActualComponentSize().getY() / (double)Constants.height ;
		return (y * scale);
	}
	
	public static double actualToInternalX(double x){
		double scale = Constants.width / (double)Main.getActualComponentSize().getX();
		return  (x * scale);
	}
	
	public static double actualToInternalY(double y){
		double scale = Constants.height / (double) Main.getActualComponentSize().getY() ;
		return (y * scale);
	}

	

	public static PointADT getActualComponentSize() {
		return new PointADT(game.getSize().width
				- (game.getInsets().left + game.getInsets().right),
				game.getSize().height
						- (game.getInsets().bottom + game.getInsets().top));
	}

	public static PointADT getContentPanelLocation() {
		return new PointADT(game.getLocation().x + game.getInsets().left,
				game.getLocationOnScreen().y + game.getInsets().top);
	}

	public static void toggleFullScreen() {

	}
	
	
	
	
	
	
	
	
	//Methods from component listener

	public void componentResized(ComponentEvent e) {
		if (this.CurrentUI != null)
			this.CurrentUI.componentResized(e);
	}
	
	public void componentMoved(ComponentEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void componentShown(ComponentEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void componentHidden(ComponentEvent e) {
		// TODO Auto-generated method stub
		
	}

	
	//methods from window listener
	
	public void windowClosing(WindowEvent e) {
		if(CurrentUI instanceof GalaxyMap || CurrentUI instanceof LocalMap) {
			SaveFile.SaveCurrentFile();
		}
	}

	public void windowOpened(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}

	

	public void windowClosed(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void windowIconified(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void windowDeiconified(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void windowActivated(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void windowDeactivated(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}
	
	
}
